#pragma once 

#include <map>
#include <string>
#include <mutex>
#include <algorithm>
#include <cstdint>
#include "OverlapPlugin.h"
#include "DllLoader.h"

using namespace std;

class OverlapPluginLoader
{
public:
	OverlapPluginLoader(const std::wstring& modname);
	virtual ~OverlapPluginLoader();

	void import();

	virtual bool Inited();
	void Close();
	const wchar_t* Name();

	const wchar_t* ErrorInfo();//err of the plugin

	wstring &LastError() { return _err; }

	OverlapPlugin* Plugin()
	{
		return m_plugin;
	}
private:
	PluginProc m_proc;
    CDllLoader m_loader;
	OverlapPlugin *m_plugin;
	wstring _name;
	wstring _err;
};

class OverlapPluginMgr
{
private:
	OverlapPluginMgr();
	OverlapPluginMgr(const OverlapPluginMgr&){}
	OverlapPluginMgr& operator=(const OverlapPluginMgr&){}
	~OverlapPluginMgr();

	int RescanPlugins(string path, std::map<wstring, OverlapPluginLoader*> &plugin_map);
	void SetDefaultDecoder();

public:
	static OverlapPluginMgr* m_pInst;
	static OverlapPluginMgr* getInstance()
	{
		static OverlapPluginMgr _instance;
		return &_instance;
	}

	OverlapPlugin* getDecoder(wstring name){
		try{
			return decoders.at(name)->Plugin();
		}
		catch (std::out_of_range&){
			return decoders.at(default_decoder)->Plugin();
		}
	}

	OverlapPlugin* getDecoder(int index){
		try{
			return decoders.at(vendorOverlap[index])->Plugin();
		}
		catch (std::out_of_range&){
			return decoders.at(default_decoder)->Plugin();
		}
	}

	wstring &getDefaultDecoderName()
	{
		return default_decoder;
	}

private:
	std::map<wstring, OverlapPluginLoader*> decoders;
	std::map<int,wstring> vendorOverlap;
	wstring default_decoder;
	wstring current_decoder;
};